﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Collections;
using Microsoft.SharePoint;
using JohnHolliday.Caml.Net;
using System.Text;
using Microsoft.SharePoint.Utilities;
using System.IO;

/// <summary>
/// Summary description for SharepointInformation
/// </summary>
public class SharepointInformation
{
	public SharepointInformation()
	{
		//
		// TODO: Add constructor logic here
		//
	}
    /// <summary>
    /// It returns an XMLDocument with the all the lists within the Url that matches the Server Template
    /// the format for the XML is the next one:
    /// <Lists> < Picutres Title='sometitle' ID='someid' /></Lists>
    /// </summary>
    /// <param name="Url">Url of the lists.asmx webservice</param>
    /// <param name="ServerTemplate">Announcements 104 Contacts 105 Custom List 100 Custom List in Datasheet View 120 DataSources
    ///110 Discussion Board 108 Document Library 101 Events 106 Form Library 115 Issues 1100 Links 103 Picture Library 109
    /// Survey 102 Tasks 107</param>
    /// <returns>XMLDocument <Lists> < Picutres Title='sometitle' ID='someid' /></Lists></returns>
    public static XmlDocument GetListColletionXML(string Url, int ServerTemplate)
    {
        ImageEnhancer.ListServiceLocal.Lists listService = new ImageEnhancer.ListServiceLocal.Lists();
        listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
        //listService.Url = "http://jmackenzie01dt:30237/sites/develop/_vti_bin/lists.asmx";
        listService.Url = Url + "/_vti_bin/lists.asmx";
        //System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
        System.Xml.XmlNode allLists = listService.GetListCollection();
        //System.Xml.XmlNodeList  ndListquery = WebServAPIT.RunXPathQuery(ndLists, "//sp:List");
        ////////XmlDocument allListsDoc = new XmlDocument();
        ///////allListsDoc.LoadXml(allLists.OuterXml);
        XmlNodeList dlNode = SharepointInformation.RunXPathQuery(allLists, "//sp:List[@ServerTemplate='" + (Int32)ServerTemplate + "']"); //allListsDoc.SelectSingleNode("/d:Lists/d:List[@='" + "109" + "']", ns);
        string document;
        //if you want to access the atribute directly
        //dlNode.Item(1).Attributes["Title"].Value
        document = "<Lists>";
        foreach (XmlNode node in dlNode)
        {
            //if want to loop tru all the attributes
            ///////foreach (XmlAttribute MatchingNodeProperty in node.Attributes)
            document += "<Picutres Title='" + node.Attributes["Title"].Value + "' ID='" + node.Attributes["ID"].Value + "' />";
        }
        document += "</Lists>";
        //find the fastest way
        //IEnumerator ienum = dlNode.GetEnumerator();
        /*while (ienum.MoveNext())
        {
            XmlNode title = (XmlNode)ienum.Current;
            //System.Xml.XmlNode thisList = listService.GetList(;
            //XmlNodeList dlNode = WebServAPIT.RunXPathQuery(thisList, "//sp:Field"); //allListsDoc.SelectSingleNode("/d:Lists/d:List[@='" + "109" + "']", ns);
            Console.Write(title.OuterXml);
        }*/
        //Console.Write(allLists.OuterXml);
        Console.ReadLine();
        XmlDocument xmldocument = new XmlDocument();
        xmldocument.LoadXml(document);
        return xmldocument;
    }
    public static XmlNodeList RunXPathQuery(XmlNode XmlNodeToQuery, string
XPathQuery)
    {
        // load the complete XML node and all its child nodes into a XML document
        XmlDocument Document = new XmlDocument();
        Document.LoadXml(XmlNodeToQuery.OuterXml);
        // all the possible namespaces used by SharePoint and a randomly choosen prefix
        const string SharePointNamespacePrefix = "sp";
        const string SharePointNamespaceURI =
       "http://schemas.microsoft.com/sharepoint/soap/";
        const string ListItemsNamespacePrefix = "z";
        const string ListItemsNamespaceURI = "#RowsetSchema";
        const string PictureLibrariesNamespacePrefix = "y";
        const string PictureLibrariesNamespaceURI =
       "http://schemas.microsoft.com/sharepoint/soap/ois/";
        const string WebPartsNamespacePrefix = "w";
        const string WebPartsNamespaceURI =
       "http://schemas.microsoft.com/WebPart/v2";
        const string DirectoryNamespacePrefix = "d";
        const string DirectoryNamespaceURI =
       "http://schemas.microsoft.com/sharepoint/soap/directory/";
        // now associate with the xmlns namespaces (part of all XML nodes returned
        // from SharePoint) a namespace prefix which we can then use in the queries
        XmlNamespaceManager NamespaceMngr = new
       XmlNamespaceManager(Document.NameTable);
        NamespaceMngr.AddNamespace(SharePointNamespacePrefix,
       SharePointNamespaceURI);
        NamespaceMngr.AddNamespace(ListItemsNamespacePrefix,
       ListItemsNamespaceURI);
        NamespaceMngr.AddNamespace(PictureLibrariesNamespacePrefix,
       PictureLibrariesNamespaceURI);
        NamespaceMngr.AddNamespace(WebPartsNamespacePrefix, WebPartsNamespaceURI);
        NamespaceMngr.AddNamespace(DirectoryNamespacePrefix,
       DirectoryNamespaceURI);
        // run the XPath query and return the result nodes
        return Document.SelectNodes(XPathQuery, NamespaceMngr);

    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="SiteUrl">Self descriptive</param>
    /// <param name="CurrentListName">Current list name, the actual list that is going to store the newly
    /// created Image enhancer</param>
    /// <param name="CustomFieldName">Custom Image Field Type created in the list where the picture library
    /// are going to be stored (ImageEnhancerCustomField)</param>
    /// <param name="AttributeName">Name of the attribute within the Field Schema (CustomImageStorage)</param>
    /// <param name="PictureLibrarytoAim">This is where the pictures are going to be stored</param>
    /// /// <summary>
    /// siteurl, listname, nameimagecustomfield(ImageEnhancerCustomField), attribute name(CustomImageStorage), 
    /// picture library (to store images (ListName))
    /// </summary>
    public static void ListChangeProperty(string SiteUrl,string CurrentListId, string CustomFieldName,
string AttributeName, string PictureLibrarytoAim    )
    {

        using (SPSite site = new SPSite(SiteUrl))
        {
            using (SPWeb web = site.OpenWeb())
            {
                string qsListId = CurrentListId;
                qsListId = CurrentListId.Replace('{', ' ').Trim();
                qsListId = qsListId.Replace('}', ' ').Trim();
                bool add = true;
                Guid _listGuid = new Guid(qsListId);
                SPList list = web.Lists[_listGuid];
                try
                {
                    foreach (SPField field in list.Fields)
                    {
                        if (field.GetType().Name.Equals(CustomFieldName))
                        {
                            //si tiene un campo que es imagecustom y es este field
                            XmlDocument xmldocument = new XmlDocument();
                            xmldocument.LoadXml(field.SchemaXml);
                            if (xmldocument.FirstChild.Attributes.GetNamedItem(AttributeName) != null)
                            {
                                xmldocument.FirstChild.Attributes[AttributeName].Value = PictureLibrarytoAim;
                                field.SchemaXml = xmldocument.InnerXml.ToString();
                                //xmldocument.Attributes["CustomImageStorage"].Value;
                                field.SchemaXml.Replace("/>", AttributeName + "=\"" + PictureLibrarytoAim + "\"");
                                add = false;
                                //break;
                            }
                            else
                            {


                                XmlNode nodetoadd = xmldocument.DocumentElement;
                                //XmlElement elem = xmldocument.CreateElement(AttributeName);
                                XmlAttribute elem = xmldocument.CreateAttribute(AttributeName);
                                elem.InnerText = PictureLibrarytoAim;
                                xmldocument.FirstChild.Attributes.Append(elem);
                                field.SchemaXml = xmldocument.InnerXml.ToString();
                                //Add the node to the document.
                                //xmldocument.DocumentElement.Attributes.Append(elem);
                                //nodetoadd.AppendChild(elem);
                                //xmldocument.Save(Console.Out);
                                //xmldocument.FirstChild.Attributes.Append(
                                //break;
                            }



                        }
                    }
                }
                catch (Exception ex) { 
                
                }
            }
        }

    }

    /// <summary>
    /// This function will query for custom types and the return an array with the Custom Image storage area (A picturelibrary name)
    /// 
    /// </summary>
    /// <param name="siteurl">Example "http://jmackenzie01dt:30237/sites/develop"</param>
    /// <param name="listname">Example "Tasks"</param>
    /// <param name="PropertyToRetrieve">Example "CustomImageStorage" attribute bound to the customfield</param>
    /// <returns></returns>
    public static System.Collections.Specialized.NameValueCollection QueryCustType(string siteurl, string listname, string Attribute)
    {
        System.Collections.Specialized.NameValueCollection returns = new System.Collections.Specialized.NameValueCollection();
        returns["0"] = false.ToString();
        try
        {
            using (SPSite site = new SPSite(siteurl))
            {
                using (SPWeb web = site.OpenWeb())
                {   //This is the list to use Within the site
                    SPList list = web.Lists[listname];
                    XmlDocument xmldocument = new XmlDocument();
                    //Load the XMLSchema of all the fields of the "Tasks" List
                    xmldocument.LoadXml(list.Fields.SchemaXml);
                    //Copy the schema to a XMLNode type variable
                    System.Xml.XmlNode allfields = xmldocument.Clone();
                    //Query the node containing the fields in order to find just those of the Type 'CustomField'
                    XmlNodeList dlNode = SharepointInformation.RunXPathQuery(allfields, "//Fields/Field[@Type='ImageEnhancerCustomField']"); //allListsDoc.SelectSingleNode("/d:Lists/d:List[@='" + "109" + "']", ns);
                    //Loop tru all the records after the query
                    foreach (XmlNode Node in dlNode)
                    {
                        returns["NODES"] = true.ToString();
                        //store Name and CustomImageStorage information in an array just for fun
                        //Note that there has to be a couple of validation before accesing the fields like this
                        if (Node.OuterXml.Contains("CustomImageStorage") && Node.OuterXml.Contains("Name"))
                        {
                            //Node.Attributes["Name"].Value
                            returns[SharepointInformation.EncodeEscapeChars(Node.Attributes["Name"].Value.ToString())] = Node.Attributes[Attribute].Value;
                            returns["0"] = true.ToString();
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //write some exception code here.
            return returns;
        }
        return returns;
    }

    public static string EncodeEscapeChars(string escaped) {
        string str;
        try
        {
            if (escaped.Contains("_"))
            {
                str = escaped.Substring(escaped.IndexOf('_'), 7);
                switch (str)
                {
                    case "_x0020_":
                        escaped = escaped.Replace("_x0020_", " ");
                        break;
                    case "_x0026_":
                        escaped = escaped.Replace("_x0026_", "&");
                        break;
                    case "_x0027_":
                        escaped = escaped.Replace("_x0027_", "'");
                        break;
                    case "_x002d_":
                        escaped = escaped.Replace("_x002d_", "-");
                        break;
                    case "_x005f_":
                        escaped = escaped.Replace("_x005f_", "_");
                        break;
                    case "_x007b_":
                        escaped = escaped.Replace("_x007b_", "{");
                        break;
                    case "_x007d_":
                        escaped = escaped.Replace("_x007d_", "}");
                        break;
                    default:
                        break;
                }
            }
        }
        catch (Exception e) { 
            
        }
        return escaped;
    }

    /// <summary>
    /// same as last one butoverload the second parameter changed
    /// This function will query for custom types and the return an array with the Custom Image storage area (A picturelibrary name)
    /// 
    /// </summary>
    /// <param name="siteurl">Example "http://jmackenzie01dt:30237/sites/develop"</param>
    /// <param name="listname">Example "Tasks" Guid</param>
    /// <param name="PropertyToRetrieve">Example "CustomImageStorage" attribute bound to the customfield</param>
    /// <returns></returns>
    public static System.Collections.Specialized.NameValueCollection QueryCustType(string siteurl, Guid listname, string Attribute)
    {
        System.Collections.Specialized.NameValueCollection returns = new System.Collections.Specialized.NameValueCollection();
        returns["0"] = false.ToString();
        try
        {
            using (SPSite site = new SPSite(siteurl))
            {
                using (SPWeb web = site.OpenWeb())
                {   //This is the list to use Within the site
                    SPList list = web.Lists[listname];
                    XmlDocument xmldocument = new XmlDocument();
                    //Load the XMLSchema of all the fields of the "Tasks" List
                    xmldocument.LoadXml(list.Fields.SchemaXml);
                    //Copy the schema to a XMLNode type variable
                    System.Xml.XmlNode allfields = xmldocument.Clone();
                    //Query the node containing the fields in order to find just those of the Type 'CustomField'
                    XmlNodeList dlNode = SharepointInformation.RunXPathQuery(allfields, "//Fields/Field[@Type='ImageEnhancerCustomField']"); //allListsDoc.SelectSingleNode("/d:Lists/d:List[@='" + "109" + "']", ns);
                    //Loop tru all the records after the query
                    foreach (XmlNode Node in dlNode)
                    {
                        returns["NODES"] = true.ToString();
                        //store Name and CustomImageStorage information in an array just for fun
                        //Note that there has to be a couple of validation before accesing the fields like this
                        if (Node.OuterXml.Contains("CustomImageStorage") && Node.OuterXml.Contains("Name"))
                        {
                            returns[Node.Attributes["Name"].Value] = Node.Attributes[Attribute].Value;
                            returns["0"] = true.ToString();
                        }
                        
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //write some exception code here.
            return returns;
        }
        return returns;
    }


    /// <summary>
    /// Upload an image to an specific sharepoint library and folder
    /// </summary>
    /// <param name="serviceurl">Url of the Imaging.asmx ej. http://jmackenzie01dt:30237/sites/develop/_vti_bin/Imaging.asmx</param>
    /// <param name="picturepath">Path of the actual image "c:\\Sunset.jpg"</param>
    /// <param name="picturelibrary">Name of the picture library where to store the pictures</param>
    /// <param name="folder">Folder inside the picture library "" for no folder</param>
    public static string UploadImage(string serviceurl, Stream fs , string picturelibrary, string folder, string filename, SPWeb web)
    {
        string thumbnail = null;
        try
        {           //validations/////////////////////////string picturepath
            if (serviceurl.Trim().EndsWith("/")) serviceurl = "_vti_bin/Imaging.asmx";
            else serviceurl += "/_vti_bin/Imaging.asmx";

            ////////////////////////////////System.IO.FileStream fs = new System.IO.FileStream(picturepath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            //Get the content
            //Stream fs = flUpload.PostedFile.InputStream;
            byte[] content = new byte[fs.Length];
            //store the content
            fs.Read(content, 0, (int)fs.Length);

            SPSecurity.RunWithElevatedPrivileges(
               new SPSecurity.CodeToRunElevated(
               delegate
               {
                   
            ImageEnhancer.ImageServiceLocal.Imaging img = new ImageEnhancer.ImageServiceLocal.Imaging();
            //set url SPContext.Current.Web.Url  http://jmackenzie01dt:30237/sites/develop
            img.Url = serviceurl;
            //Set credential
            img.Credentials = System.Net.CredentialCache.DefaultCredentials;
            //for results
            System.Xml.XmlDocument resdoc = new System.Xml.XmlDocument();
            System.Xml.XmlNode resnode = resdoc.CreateNode(System.Xml.XmlNodeType.Element, "Result", "");
            //Create the filestream


            try
            {
                //Upload the file - specify "" for root folder, for sub folders specify 1, 2, 3 relative to the folder number
                resnode = img.Upload(picturelibrary, folder, content, filename, true);
                //img.UploadAsync(picturelibrary, folder, content, filename, true);
            }
            catch (Exception ex) { 
                //
            }
            thumbnail = SharepointInformation.GetPictureUrl(web.Lists[picturelibrary].Items[web.Lists[picturelibrary].Items.Count - 1], SharepointInformation.ImageSize.Thumbnail);
            //thumbnail = SharepointInformation.GetPictureUrl(web.Lists[picturelibrary].Items[0], SharepointInformation.ImageSize.Thumbnail);
            filename = filename.Replace('.', '_');
            thumbnail = thumbnail.Substring(0, thumbnail.LastIndexOf("/")+1);
            thumbnail += filename+".jpg";
            //Console.Write(resnode.OuterXml);
               }));
        }
        catch (Exception ex)
        {

            
            return "You dont have permissions to open/modify that picture, pick one with permissions" + ex.ToString().Substring(0,20);
        }
        return thumbnail;

    }
    public static string GetPictureUrl(SPListItem listItem, ImageSize imageSize)
    {
        StringBuilder url = new StringBuilder();
        // Build the url up until the final portion
        url.Append(SPEncode.UrlEncodeAsUrl(listItem.ParentList.ParentWebUrl));
        url.Append('/');
        url.Append(SPEncode.UrlEncodeAsUrl(listItem.ParentList.RootFolder.Url));
        url.Append('/');
        // Determine the final portion based on the requested image size
        string filename = listItem.File.Name;
        if (imageSize == ImageSize.Full)
        {
            url.Append(SPEncode.UrlEncodeAsUrl(filename));
        }
        else
        {
            string basefilename = Path.GetFileNameWithoutExtension(filename);
            string extension = Path.GetExtension(filename);
            string dir = (imageSize == ImageSize.Thumbnail) ? "_t/" : "_w/";
            url.Append(dir);
            url.Append(SPEncode.UrlEncodeAsUrl(basefilename));
            url.Append(SPEncode.UrlEncodeAsUrl(extension).Replace('.', '_'));
            url.Append(".jpg");
        }
        return url.ToString();

    }
    public enum ImageSize
    {
        Thumbnail,
        Large,
        Full
    }
    
}
